package org.whatever.aha.zjut.platform.controller.project;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.thread.ThreadUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.whatever.aha.zjut.base.constant.ErrorCode;
import org.whatever.aha.zjut.base.constant.MsgTypeRedisConstant;
import org.whatever.aha.zjut.base.constant.StatusConstant;
import org.whatever.aha.zjut.base.dto.AjaxResult;
import org.whatever.aha.zjut.base.exception.AppException;
import org.whatever.aha.zjut.platform.annotation.ProjectPermission;
import org.whatever.aha.zjut.platform.dto.project.ProjectMemberDto;
import org.whatever.aha.zjut.platform.entity.competition.CompetitionStageStatus;
import org.whatever.aha.zjut.platform.message.MessageService;
import org.whatever.aha.zjut.platform.service.StudentInfoService;
import org.whatever.aha.zjut.platform.service.UserService;
import org.whatever.aha.zjut.platform.service.competition.CompetitionService;
import org.whatever.aha.zjut.platform.service.competition.CompetitionStageStatusService;
import org.whatever.aha.zjut.platform.service.project.ProjectMemberService;
import org.whatever.aha.zjut.platform.service.project.ProjectService;
import org.whatever.aha.zjut.platform.util.CheckUtil;
import org.whatever.aha.zjut.platform.vo.project.ProjectDetailVo;
import org.whatever.aha.zjut.platform.vo.project.ProjectMemberDetailVo;
import org.whatever.aha.zjut.platform.vo.project.ProjectMemberVo;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Vc
 * @version 1.0
 * @Desc
 * @date 2021/09/17 0:30
 */
@Api(tags = "项目成员操作类")
@RequestMapping("/v1/projectMember")
@RequiredArgsConstructor
@RestController
@Validated
public class ProjectMemberController {
    final ProjectMemberService projectMemberService;
    final ProjectService projectService;
    final StudentInfoService studentInfoService;
    final CompetitionService competitionService;
    final CompetitionStageStatusService competitionStageStatusService;
    final MessageService messageService;
    final UserService userService;

    @ProjectPermission
    @ApiOperation("根据项目成员ID添加项目成员")
    @PostMapping("/addMember")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "项目成员ID", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "rank", value = "项目成员排位", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "job", value = "项目成员职责", dataTypeClass = Integer.class)
    })
   AjaxResult<String> addProjectMemberByProjectId(@RequestParam("userId")int userId,@RequestParam("projectId") int projectId ,@RequestParam("rank") int rank, @RequestParam("job") String job){
        //提交阶段 && 项目未提交
        ProjectDetailVo projectDetail = projectService.getProjectDetailById(projectId);
        CompetitionStageStatus singleCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(projectDetail.getStageId(), StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode());
        CheckUtil.checkTimeLimit(singleCompStageStatus.getStatusStartTime(), singleCompStageStatus.getStatusEndTime());
        CheckUtil.checkStuStatus(StatusConstant.PROJECT_STUDENT_STATUS_WAIT_FOR_SUBMIT.getCode(), projectService.getProjectStuStatus(projectId));

        //项目成员检验
        ProjectMemberDto dto = new ProjectMemberDto(userId, rank, job);
        List<ProjectMemberDto> memberDtos = new ArrayList<ProjectMemberDto>(Arrays.asList(dto));
        int leaderId = StpUtil.getLoginIdAsInt();
        List<ProjectMemberVo> memberRough = projectMemberService.getMemberRough(projectId);
        List<Integer> memberIds = memberRough.stream().map(ProjectMemberVo::getMemberId).collect(Collectors.toList());
        List<Integer> memberRanks = memberRough.stream().map(ProjectMemberVo::getProjectMemberRank).collect(Collectors.toList());
        CheckUtil.checkProjectMember(memberDtos, memberIds, memberRanks, ((int)competitionService.getMemberLimit((int) projectService.getCompIdByProjectId(projectId))-1), leaderId);

        String affectRow = projectMemberService.addProjectMemberByProjectId(userId, projectId, rank, job);
        //发送站内信
        SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String sendTime = s.format(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime());
        Integer curUser = StpUtil.getLoginIdAsInt();
        messageService.createUserMessage(StatusConstant.MSG_SYS_SENDER.getCode(), userId, sendTime,
                MsgTypeRedisConstant.MSG_TYPE_IN_TEAM_TITLE, MsgTypeRedisConstant.getKeyInTeam(curUser, userService.getUserRoughInfoById(curUser).getUserName(), "邀请加入", projectDetail.getProjectName(), rank),
                MsgTypeRedisConstant.MSG_SYS_NAME, StatusConstant.MSG_TYPE_IN_TEAM.getCode());
        return AjaxResult.SUCCESS(affectRow);

   }

    @ProjectPermission
    @ApiOperation("根据项目id和用户id删除项目成员")
    @DeleteMapping("/{projectId}/{userId}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "项目成员ID", dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class)
    })
   AjaxResult<Integer> deleteProjectMember(@PathVariable("userId")int userId, @PathVariable("projectId") int projectId){
        //提交阶段 && 项目未提交
        ProjectDetailVo projectDetail = projectService.getProjectDetailById(projectId);
        CompetitionStageStatus singleCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(projectDetail.getStageId(), StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode());
        CheckUtil.checkTimeLimit(singleCompStageStatus.getStatusStartTime(), singleCompStageStatus.getStatusEndTime());
        CheckUtil.checkStuStatus(StatusConstant.PROJECT_STUDENT_STATUS_WAIT_FOR_SUBMIT.getCode(), projectService.getProjectStuStatus(projectId));

        //不可以删除leader
        if((int)projectService.getLeaderId(projectId) != userId){
            int affectRow = projectMemberService.deleteProjectMember(projectId, userId);
            //发送站内信
            ProjectMemberVo projectMemberVo = projectMemberService.getProjectMemberVoById(userId, projectId);
            SimpleDateFormat s=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String sendTime = s.format(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime());
            Integer curUser = StpUtil.getLoginIdAsInt();
            messageService.createUserMessage(StatusConstant.MSG_SYS_SENDER.getCode(), userId, sendTime,
                    MsgTypeRedisConstant.MSG_TYPE_IN_TEAM_TITLE, MsgTypeRedisConstant.getKeyInTeam(curUser, userService.getUserRoughInfoById(curUser).getUserName(), "踢出", projectDetail.getProjectName(), projectMemberVo.getProjectMemberRank()),
                    MsgTypeRedisConstant.MSG_SYS_NAME, StatusConstant.MSG_TYPE_IN_TEAM.getCode());
            return AjaxResult.SUCCESS(affectRow);
        }else {
            throw new AppException(ErrorCode.OPERATION_FORBIDDEN_DELETE_LEADER);
        }
   }

    @ProjectPermission
    @ApiOperation("根据项目id更新项目成员")
    @PutMapping("/{projectId}")
    @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class)
    AjaxResult<Object> updateProjectMember(@PathVariable("projectId") int projectId,@RequestBody ProjectMemberDto projectMemberDto){
        //提交阶段 && 项目未提交
        CompetitionStageStatus singleCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(projectService.getProjectDetailById(projectId).getStageId(), StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode());
        CheckUtil.checkTimeLimit(singleCompStageStatus.getStatusStartTime(), singleCompStageStatus.getStatusEndTime());
        CheckUtil.checkStuStatus(StatusConstant.PROJECT_STUDENT_STATUS_WAIT_FOR_SUBMIT.getCode(), projectService.getProjectStuStatus(projectId));


        //项目成员检验
        List<ProjectMemberDto> memberDtos = new ArrayList<ProjectMemberDto>(Arrays.asList(projectMemberDto));
        int userId = StpUtil.getLoginIdAsInt();
        List<ProjectMemberVo> memberRough = projectMemberService.getMemberRough(projectId);
        List<Integer> memberIds = memberRough.stream().map(ProjectMemberVo::getMemberId).collect(Collectors.toList());
        List<Integer> memberRanks = memberRough.stream().map(ProjectMemberVo::getProjectMemberRank).collect(Collectors.toList());
        CheckUtil.checkProjectMember(memberDtos, memberIds, memberRanks, ((int)competitionService.getMemberLimit((int) projectService.getCompIdByProjectId(projectId))-1), userId);

        return AjaxResult.SUCCESS(projectMemberService.updateProjectMember(projectMemberDto, projectId));

//        if(!projectMemberService.getRankList(projectId,projectMemberDto.getMemberId()).contains(projectMemberDto.getProjectMemberRank())){
//            return AjaxResult.SUCCESS(projectMemberService.updateProjectMember(projectMemberDto, projectId));
//        }else{
//            throw new AppException(ErrorCode.RANK_ALREADY_EXIST);
//        }
    }


    @ProjectPermission
    @ApiOperation("批量更新项目成员")
    @PutMapping("/updateBatch/{projectId}")
    @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class)
    AjaxResult<String> updateProjectMember(@PathVariable("projectId") int projectId,@RequestBody List<ProjectMemberDto> projectMemberDtos){
        //提交阶段 && 项目未提交
        CompetitionStageStatus singleCompStageStatus = competitionStageStatusService.getSingleCompStageStatus(projectService.getProjectDetailById(projectId).getStageId(), StatusConstant.COMPETITION_STAGE_STATUS_ORDER_SUBMIT.getCode());
        CheckUtil.checkTimeLimit(singleCompStageStatus.getStatusStartTime(), singleCompStageStatus.getStatusEndTime());
        CheckUtil.checkStuStatus(StatusConstant.PROJECT_STUDENT_STATUS_WAIT_FOR_SUBMIT.getCode(), projectService.getProjectStuStatus(projectId));

        //项目成员检验
        List<ProjectMemberDto> memberDtos = new ArrayList<ProjectMemberDto>(projectMemberDtos);
        int userId = StpUtil.getLoginIdAsInt();
        List<ProjectMemberVo> memberRough = projectMemberService.getMemberRough(projectId);
        List<Integer> memberIds = memberRough.stream().map(ProjectMemberVo::getMemberId).collect(Collectors.toList());
        List<Integer> memberRanks = memberRough.stream().map(ProjectMemberVo::getProjectMemberRank).collect(Collectors.toList());
        CheckUtil.checkProjectMember(memberDtos, memberIds, memberRanks, ((int)competitionService.getMemberLimit((int) projectService.getCompIdByProjectId(projectId))-1), userId);


        return AjaxResult.SUCCESS(projectMemberService.updateProjectMembers(projectMemberDtos, projectId));
    }

    /**
     * 查询得到当前项目的最低排位
     *
     * @param projectId
     * @return 如果成员满了返回0，否则返回最小的rank
     */
    @ApiOperation("查询得到当前项目的最低排位")
    @GetMapping("/getRank/{projectId}")
    @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class)
    AjaxResult<Integer> getRank(@PathVariable("projectId")int projectId){
        return AjaxResult.SUCCESS(projectMemberService.getRank(projectId));
    }

    @ApiOperation("获得当前项目所有粗略成员信息（只包含团队信息）")
    @GetMapping("/getMemberRough/{projectId}")
    @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class)
    AjaxResult<List<ProjectMemberVo>> getMemberRough(@PathVariable("projectId")int projectId){
        return AjaxResult.SUCCESS(projectMemberService.getMemberRough(projectId));
    }

    @ApiOperation("获得当前项目所有详细成员信息（包含个人学号等）")
    @GetMapping("/getMemberDetail/{projectId}")
    @ApiImplicitParam(name = "projectId", value = "项目Id", dataTypeClass = Integer.class)
    AjaxResult<List<ProjectMemberDetailVo>> getMemberDetail(@PathVariable("projectId")int projectId){
        return AjaxResult.SUCCESS(projectMemberService.getMemberDetail(projectId));
    }
}
